<?php
namespace XFCore\traits\api;
use lib\{Examine,Tips,PayUtils,AesRsa_Encrypter};
/*
*支付发起 及内部回调处理
*/
trait PayTrait{
    
    public function submit(){
        
        $queryArr = input();
        
        $pid=intval($queryArr['pid']);
        $userrow = $this->db->userrow($pid , 'pid');
        
        if(empty($userrow)){
            $this->sys_msg('商户不存在');
        }
        
        if($userrow['api_mode'] == 2){
            if(empty($queryArr['token'])){
                $this->sys_msg('token不可为空');
            }
            $queryArr = $this->decodersatoken($userrow , $queryArr['token']);
            if($queryArr === false){
                $this->sys_msg('token错误！');
            }
        
        }
        $this->Examine_EmptyData($queryArr);
        $this->Examine_User($queryArr , $userrow);
        if(SubmitSign)$this->Examine_Sign($queryArr , $userrow);
        $this->Examine_Order($queryArr);
        
        $queryArr['qr_id'] = $this->Pick_Qr($queryArr, $userrow)['id'];
        $queryArr['price'] = $this->Compute_amount($queryArr , $userrow);
        
        $queryArr['trade_no'] = date("YmdHis").rand(11111,99999);
        
        $queryArr['pay_id'] = !empty($queryArr['clientip'])?$queryArr['clientip']:http_ip();
        $queryArr['pay_sign'] = 'submit';
        if(!$this->Add_Order($queryArr , $userrow)){
            $this->sys_msg("写入订单失败 请检查数据 是否合法且完整");
        }
        $this->Skip_Pay($queryArr['trade_no']);
    }
    public function mapi(){
        $queryArr = input();
        
        $pid=intval($queryArr['pid']);
        $userrow = $this->db->userrow($pid , 'pid');
        
        if(empty($userrow)){
            $this->sys_msg('商户不存在',true);
        }
        
        if($userrow['api_mode'] == 2){
            if(empty($queryArr['token'])){
                $this->sys_msg('token不可为空',true);
            }
            $queryArr = $this->decodersatoken($userrow , $queryArr['token']);
            if($queryArr === false){
                $this->sys_msg('token错误！',true);
            }
        
        }
        $this->Examine_EmptyData($queryArr,true);
        $this->Examine_User($queryArr , $userrow,true);
        if(SubmitSign)$this->Examine_Sign($queryArr , $userrow,true);
        $this->Examine_Order($queryArr,true);
        $queryArr['qr_id'] = $this->Pick_Qr($queryArr, $userrow,true)['id'];
        $queryArr['price'] = $this->Compute_amount($queryArr , $userrow,true);
        $queryArr['trade_no'] = date("YmdHis").rand(11111,99999);
        
        $queryArr['pay_id'] = !empty($queryArr['clientip'])?$queryArr['clientip']:http_ip();
        $queryArr['pay_sign'] = 'mapi';
        if(!$this->Add_Order($queryArr , $userrow)){
            $this->sys_msg("写入订单失败 请检查数据 是否合法且完整");
        }
        $data = $this->mapi_qrcode($queryArr , $userrow);
        $a = [
            'money'=>$queryArr['price'],
            'type'=>$queryArr['type'],
            'qrcode'=>$data['qrcode'],
            'code_url'=>$data['code_url'],
            'trade_no'=>$queryArr['trade_no'],
            "out_trade_no"=>$queryArr['out_trade_no']
        ];
        exitjson(1,"发起成功,请支付".$queryArr['price']."元,不要多付也不要少付",$a);
    }
    public function pay_submit(){
        $token = $this->input->token;
        if(empty($token)){
            $this->sys_msg('token为空发起失败',true);
        }
        $params = json_decode(aes256auth($token , SYS_KEY , 'DECODE') , true);
        if(empty($params) ){
            $this->sys_msg('非法操作',true);
        }
        //检查订单是否存在
        $row = $this->db->select('insideorder','*',['status'=>0,'order'=>$params['out_trade_no']],['single_row'=>true,'limit'])['result'];
        if(empty($row)){
            $this->sys_msg('订单写入失败',true);
        }
        
        $this->Examine_EmptyData($params,true);
        $userrow = $this->db->userrow($params['pid'] , 'pid');
        if(empty($userrow)){
            $this->sys_msg('商户不存在',true);
        }
        $this->Examine_User($params , $userrow , true);
        $this->Examine_Order($params,true);
        $params['qr_id'] = $this->Pick_Qr($params, $userrow,true)['id'];
        $params['price'] = $this->Compute_amount($params , $userrow,true);
        $params['pay_id'] = !empty($params['clientip'])?$params['clientip']:http_ip();
        $params['pay_sign'] = 'submit';
        if(!$this->Add_Order($params , $userrow)){
            $this->sys_msg("写入订单失败 请检查数据 是否合法且完整",true);
        }
        exitjson(200,'success',['pay_url'=>$this->httphost . "submit/gopay/".$params['trade_no']]);
    }
    
    public function juhe_pay($get,$post){
        $data = array_merge($get , $post);
        
        $type = Web_Type();
        if(empty($type)){
            $this->sys_msg('请在微信、支付宝或QQ中发起该支付');
        }
        if(empty($data['trade_no'])){
            $this->sys_msg('参数错误请重新发起');
        }
        if(!is_numeric($data['money']) || $data['money'] <= 0){
            $this->sys_msg('金额不合法');
        }
        $arr = [
            'type'=>$type,
            'out_trade_no'=>$data['trade_no'],
            'return_url'=>$this->httphost . "juhe/succpay/xfpay",
            'notify_url'=>$this->httphost . "pay/notify/".$data['trade_no'],
            'name'=>"在线聚合收款",
            'sign'=>"xfpay123456"
        ];
        $params = array_merge($arr , $data);
        $this->Examine_EmptyData($params);
        $userrow = $this->db->userrow($params['pid'] , 'pid');
        if(empty($userrow)){
            $this->sys_msg('商户不存在');
        }
        $this->Examine_User($params , $userrow);
        $this->Examine_Order($params);
        $params['qr_id'] = $this->Pick_Qr($params, $userrow)['id'];
        $params['price'] = $this->Compute_amount($params , $userrow);
        $params['pay_id'] = !empty($params['clientip'])?$params['clientip']:http_ip();
        $params['pay_sign'] = 'submit';
        if(!$this->Add_Order($params , $userrow)){
            $this->sys_msg("写入订单失败 请检查数据 是否合法且完整");
        }
        $pay_url = $this->httphost . "submit/gopay/".$params['trade_no'];
        header("Location: " . $pay_url,301);
        exit;
    }
    public function pay_cs($get,$post){
        $data = array_merge($get , $post);
        $data['pid'] = $this->conf->zero_pid;
        if(empty($data['trade_no'])){
            $this->sys_msg('参数错误请重新发起');
        }
        if(!is_numeric($data['money']) || $data['money'] <= 0){
            $this->sys_msg('金额不合法');
        }
        
        
        $arr = [
            'out_trade_no'=>$data['trade_no'],
            'return_url'=>$this->httphost . "pay/succpay/xfpay",
            'notify_url'=>$this->httphost . "pay/notify/".$data['trade_no'],
            'name'=>"测试商品",
            'sign'=>"xfpay123456"
        ];
        $params = array_merge($arr , $data);
        $this->Examine_EmptyData($params);
        $userrow = $this->db->userrow($params['pid'] , 'pid');
        if(empty($userrow)){
            $this->sys_msg('商户不存在');
        }
        $this->Examine_User($params , $userrow);
        $this->Examine_Order($params);
        $params['qr_id'] = $this->Pick_Qr($params, $userrow)['id'];
        $params['price'] = $this->Compute_amount($params , $userrow);
        $params['pay_id'] = !empty($params['clientip'])?$params['clientip']:http_ip();
        $params['pay_sign'] = 'submit';
        if(!$this->Add_Order($params , $userrow)){
            $this->sys_msg("写入订单失败 请检查数据 是否合法且完整");
        }
        $pay_url = $this->httphost . "submit/gopay/".$params['trade_no'];
        header("Location: " . $pay_url,301);
        exit;
    }
    protected function decodersatoken($userrow,$token){
        
        $decode = AesRsa_Encrypter::decode($token,md5($userrow['key'].$userrow['pid']),aes256auth($userrow['rsaprivatekey'],SYS_KEY,'DECODE'));
        if(!$decode)return $decode;
        return json_decode($decode,true);
    }
    // 检测参数是否缺失 及合法性
    protected function Examine_EmptyData($data , $send = false) {
        
        $errorMsgs = [
            'type' => '支付方式不可为空！',
            'out_trade_no' => '订单号(out_trade_no)不能为空',
            'notify_url' => '通知地址(notify_url)不能为空',
            'return_url' => '回调地址(return_url)不能为空',
            'name' => '商品名称(name)不能为空',
            'money' => '金额(money)不能为空',
            'max_money' => '最大支付金额是' . $this->conf['pay_maxmoney'] . '元',
            'min_money' => '最小支付金额是' . $this->conf['pay_minmoney'] . '元',
            'invalid_money' => '金额不合法',
            'pid' => '商户ID不可为空！',
            'sign'=>"签名不可为空！",
            'invalid_out_trade_no' => '订单号(out_trade_no)格式不正确'
        ];
        
        // 定义需要检查的字段
        $requiredFields = [
            'out_trade_no',
            'type',
            'pid',
            'notify_url',
            'return_url',
            'name',
            'money',
            'sign'
        ];
    
        foreach ($requiredFields as $field) {
            if (empty($data[$field])) {
                $this->sys_msg($errorMsgs[$field], $send);
            }
        }
        if ($data['money'] <= 0 || !is_numeric($data['money'])){
            $this->sys_msg($errorMsgs['min_money'], $send);
        }
        if ($this->conf['pay_maxmoney'] > 0 && $data['money'] > $this->conf['pay_maxmoney']) {
            $this->sys_msg($errorMsgs['max_money'], $send);
        }
        if ($this->conf['pay_minmoney'] > 0 && $data['money'] < $this->conf['pay_minmoney']){
            $this->sys_msg($errorMsgs['min_money'], $send);
        }
        if (!preg_match('/^[a-zA-Z0-9.\_\-]+$/', $data['out_trade_no'])){
            $this->sys_msg($errorMsgs['invalid_out_trade_no'], $send);
        }
        return true;
    }
    
    //检测商户状态 及会员
    protected function Examine_User($data , $userrow = '' , $send = false){
        $errorMsgs = [
            'emptyuser'=>'商户不存在',
            'errorzt'=>'此商户已被封禁，已被禁止发起支付，如您是本支付平台商户，请联系站长',
            'insufficient_balance' => '当前商户额度不足[' . $data['money'] . ']，所以无法生成此订单,请商户们自行进行充值',
            'member_not_found' => '当前商户未开通此通道会员，所以无法生成此订单,请商户们自行进商户中心开通',
        ];
        
        if(empty($userrow)){
            $this->sys_msg($errorMsgs['emptyuser'],$send);
        }
        if($userrow['zt'] != 1){
            $this->sys_msg($errorMsgs['errorzt'],$send);
        }
        
        if ($userrow['money'] < $data['money']){
            $this->sys_msg($errorMsgs['insufficient_balance'],$send);
        }
        
        $huiyuan =($data['type'] == 'usdt') ? 'alipay' : $data['type'];
        
        $userrosc = strtotime($userrow[$huiyuan . '_free_vip_time']);
        $datemine = strtotime($this->date);
        if ($userrosc < $datemine) {
            $this->sys_msg($errorMsgs['member_not_found'],$send);
        }
        $name = $data['name'];
        $domain = getdomain($data['notify_url']);
        if (!empty($this->conf['blockname'])){
            $block_name = explode('|', $this->conf['blockname']);
            foreach ($block_name as $rows) {
                if (strpos($name, $rows) !== false) {
                    $this->db->update('user',['zt'=>0],['pid'=>$userrow['pid']]);
                    $this->db->insert('risk',['pid'=>$userrow['pid'] , 'url'=>$domain , 'content'=>$rows,'date'=>$this->date]);
                    $this->sys_msg('该商品禁止出售',$send);
                }
            }
        }
        return true;
    }
    //验证签名
    protected function Examine_Sign($data , $userrow, $send = false){
        $prestr=PayUtils::createLinkstring(PayUtils::argSort(PayUtils::paraFilter($data)));
        
        if(!PayUtils::md5Verify($prestr, $data['sign'], $userrow['key'])){
            $this->sys_msg("签名错误！",$send);
        }
        return true;
    }
    //验证商户订单号是否重复
    protected function Examine_Order($data , $send = false){
        $srow = $this->db->orderrow($data['out_trade_no'] , 'out_trade_no');
        if($srow){
            $this->sys_msg("商户订单号不能重复",$send);
        }
    }
    //选择 支付通道 并更新 通道轮询
    protected function Pick_Qr($data , $userrow , $send = false){
        $errorMsgs = [
            'alipay'=>'支付宝下单失败,暂无收款账户,或掉线',
            'wxpay'=>'微信支付下单失败,暂无收款账户,或掉线',
            'qqpay'=>'QQ支付下单失败,暂无收款账户,或掉线',
            'usdt'=>'USDT-TRC20下单失败,暂无收款账户',
            'usdtmoney'=>'USDT-TRC20下单失败,人民币金额必须大于一元'
        ];
        
        $Qr_row = $this->db->select('qrlist',"`id`,`nums`",['pid'=>$userrow['pid'] , 'type'=>$data['type'] , 'status'=>1] , ['orderBy'=>'nums ASC' , 'limit'=>1 , 'single_row'=>true])['result'];
        
        if(empty($Qr_row)){
            $this->sys_msg($errorMsgs[$data['type']] , $send);
        }
        if($data['type'] == 'usdt' && $data['money'] < 1){
            $this->sys_msg($errorMsgs['usdtmoney'] , $send);
        }
       
        
        // 检查是否需要重置 nums 字段为 0
        if($Qr_row['nums'] + 1 > 10){
            $params = [
                'nums'=>0
            ];
        }else{
            $params = [
                'nums'=>$Qr_row['nums'] + 1
            ];
        }
         
        // 更新 QR_row 的 nums 字段
        $this->db->update('qrlist',$params ,['id'=>$Qr_row['id']]);
       
        return $Qr_row;
        
    }
    /**
     * 计算订单金额并处理重复订单金额的情况
     *
     * @param string $data 订单数据
     * @param array $userrow 用户数据
     * @return float 计算后的订单金额
     */
    protected function Compute_amount($data , $userrow){
        $money = $data['money'];
        $price = ($data['type'] == 'usdt') ? $this->CurlUrl->Obtain_UsdtMoney($money) : $money;
        while (true){
            $exists = $this->db->select('order', 'price', [
                'status' => 0,
                'price' => $price,
                'pid' => $userrow['pid'],
                'type' => $data['type']
            ], [
                'limit' => 1,
                'single_row' => true
            ])['result'];
            if (!$exists) {
                break;
            }
            $price = round($price + 0.01, 2);
        }
        return $price;
    }
    protected function Add_Order($data , $userrow){
        $allowedFields = [
            'pid',
            'type',
            'out_trade_no',
            'notify_url',
            'return_url',
            'name',
            'money',
            'qr_id',
            'price',
            'trade_no',
            'pay_id',
            'param'
        ];
    
        // 只保留允许的字段
        $filteredData = array_intersect_key($data, array_flip($allowedFields));
        $outtime = isset($userrow['outtime']) ? $userrow['outtime'] : $this->conf['outtime'];
        $outtime = time() + $outtime;
        
        $outtime = ($data['type'] == 'usdt') ? time() + 1200 : $outtime;
        
        $arr = [
            'status'=>0,
            'apitime'=>time() + 10,
            'api_type'=>substr(md5(urlencode($_SERVER['HTTP_HOST'] . '_' . $data['pid'])), 8, 10) . '_' . $data['type'],
            'pay_sign'=>$data['pay_sign'],
            'outtime'=>$outtime,
            'addtime'=>$this->date
        ];
        $params = array_merge($filteredData , $arr);
        
        return $this->db->insert("order",$params);
    }
    //返回错误文本 or json
    protected function sys_msg($msg , $send = false){
        if($send){
            exitjson(-1,$msg);
        }
        Tips::error($msg , '发起失败');
    }
    protected function Skip_Pay($trade_no){
        Tips::success("发起成功正在跳转中....",'发起成功','/submit/gopay/'.$trade_no);
    }
    protected function mapi_qrcode($data , $userrow){
        $Qr_row = $this->db->qrlistrow($data['qr_id']);
        $srow   = $this->db->orderrow($data['trade_no']);
        if(empty($Qr_row) || empty($srow)){
            exitjson(-1,'未知错误！');
        }
        $data   = $this->datatypeqrcode($srow , $Qr_row ,$userrow)();
        return ['qrcode'=>$data['url'] , 'code_url'=>$data['qrcode']];
    }
}



?>